package com.socialsoftware.MediaCommunication.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.socialsoftware.MediaCommunication.model.CallMode;
import com.socialsoftware.MediaCommunication.model.CommunicationMessage;
import com.socialsoftware.MediaCommunication.model.MessageType;
import com.socialsoftware.MediaCommunication.utils.Constants;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONException;

import java.net.URI;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * Service for managing WebSocket connection for WebRTC signaling
 */
public class WebSocketService extends Service {
    private static final String TAG = "WebSocketService";
    private static final String WS_URL = "wss://192.168.125.43:8443/RemoteAddressForVideoChat";

    private WebSocketClient webSocket;
    private String username;
    private final IBinder binder = new WebSocketBinder();
    private boolean isConnected = false;

    public class WebSocketBinder extends Binder {
        public WebSocketService getService() {
            return WebSocketService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        // 不再自动生成用户名，而是等待onStartCommand中的参数
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 从Intent中获取用户名
        if (intent != null && intent.hasExtra("username")) {
            username = intent.getStringExtra("username");
            Log.d(TAG, "WebSocket服务使用用户名: " + username);
            
            try {
                // 如果用户名有变化或WebSocket未初始化，则初始化WebSocket
                if (webSocket == null) {
                    initWebSocket();
                }
            } catch (Exception e) {
                Log.e(TAG, "初始化WebSocket失败", e);
            }
        } else if (username == null) {
            Log.e(TAG, "未提供用户名，无法初始化WebSocket连接");
            return START_NOT_STICKY;
        }
        
        if (!isConnected && webSocket != null) {
            try {
                webSocket.connect();
            } catch (Exception e) {
                Log.e(TAG, "连接WebSocket失败", e);
            }
        }
        return START_STICKY;
    }

    private void initWebSocket() throws Exception {
        try {
            // 确保用户名不为空
            if (username == null || username.isEmpty()) {
                Log.e(TAG, "用户名为空，无法初始化WebSocket");
                return;
            }
            
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
            }};

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new SecureRandom());

            webSocket = new WebSocketClient(new URI(WS_URL + "?username=" + username)) {
                @Override
                public void onOpen(ServerHandshake handshakedata) {
                    Log.d(TAG, "WebSocket已连接，用户名: " + username);
                    isConnected = true;
                    broadcastConnectionStatus(true);
                }

                @Override
                public void onMessage(String message) {
                    handleWebSocketMessage(message);
                }

                @Override
                public void onClose(int code, String reason, boolean remote) {
                    Log.d(TAG, "WebSocket已关闭: " + reason);
                    isConnected = false;
                    broadcastConnectionStatus(false);
                    // 延迟尝试重新连接
                    reconnectWithDelay();
                }

                @Override
                public void onError(Exception ex) {
                    Log.e(TAG, "WebSocket错误: " + ex.getMessage());
                    isConnected = false;
                    broadcastConnectionStatus(false);
                    // 延迟尝试重新连接
                    reconnectWithDelay();
                }
            };

            webSocket.setSocketFactory(sslContext.getSocketFactory());
            javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
                    (hostname, session) -> true);
            webSocket.connect();
        } catch (URISyntaxException e) {
            Log.e(TAG, "WebSocket URI无效", e);
            throw e;
        }
    }

    private void reconnectWithDelay() {
        new Thread(() -> {
            try {
                Thread.sleep(5000); // Wait 5 seconds
                if (!isConnected && webSocket != null) {
                    initWebSocket();
                }
            } catch (Exception e) {
                Log.e(TAG, "Reconnection failed", e);
            }
        }).start();
    }

    private void handleWebSocketMessage(String message) {
        try {
            CommunicationMessage commMessage = CommunicationMessage.fromJson(message);
            String type = commMessage.getType();
            
            // 确保消息中包含通信模式
            String mode = commMessage.getMode();
            if (mode == null || mode.isEmpty()) {
                Log.w(TAG, "收到没有指定通信模式的消息，默认使用音频模式");
                mode = CallMode.AUDIO.getValue();
                commMessage.setMode(mode);
            }
            
            // Broadcast the message to any listening components
            Intent intent = new Intent(Constants.ACTION_WEBSOCKET_MESSAGE);
            intent.putExtra(Constants.EXTRA_MESSAGE_TYPE, type);
            intent.putExtra(Constants.EXTRA_MESSAGE_JSON, message);
            LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
            
            // Special handling for incoming calls to show notification even when app is in background
            if (MessageType.CALL_START.getValue().equals(type)) {
                Intent callIntent = new Intent(Constants.ACTION_INCOMING_CALL);
                callIntent.putExtra(Constants.EXTRA_CALLER_NAME, commMessage.getFromUser());
                callIntent.putExtra(Constants.EXTRA_CALL_MODE, mode);
                LocalBroadcastManager.getInstance(this).sendBroadcast(callIntent);
            }
        } catch (JSONException e) {
            Log.e(TAG, "Failed to parse WebSocket message", e);
        }
    }

    private void broadcastConnectionStatus(boolean connected) {
        Intent intent = new Intent(Constants.ACTION_WEBSOCKET_STATUS);
        intent.putExtra(Constants.EXTRA_CONNECTED, connected);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    public boolean isConnected() {
        return isConnected;
    }

    public void sendMessage(CommunicationMessage message) {
        // 确保所有消息都有通信模式
        if (message.getMode() == null || message.getMode().isEmpty()) {
            Log.w(TAG, "正在发送没有指定通信模式的消息，默认使用音频模式");
            message.setMode(CallMode.AUDIO.getValue());
        }
        
        if (webSocket != null && isConnected) {
            try {
                webSocket.send(message.toJson().toString());
            } catch (JSONException e) {
                Log.e(TAG, "Failed to serialize message", e);
            }
        } else {
            Log.e(TAG, "Cannot send message: WebSocket not connected");
            try {
                reconnectWithDelay();
            } catch (Exception e) {
                Log.e(TAG, "Failed to reconnect", e);
            }
        }
    }
    
    public void sendRejectCallMessage(String caller) {
        CommunicationMessage message = new CommunicationMessage();
        message.setType(MessageType.CALL_BACK.getValue());
        message.setFromUser(username);
        message.setToUser(caller);
        message.setMsg("0");
        message.setMode(CallMode.AUDIO.getValue()); // 拒绝通话时使用音频模式
        sendMessage(message);
    }

    @Override
    public void onDestroy() {
        if (webSocket != null) {
            webSocket.close();
            webSocket = null;
        }
        super.onDestroy();
    }

    public String getUsername() {
        return username;
    }
} 